package org.hgvc.webapp.ets.jsf.beans.finance;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.faces.component.UIParameter;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;

import org.hgvc.webapp.ets.bo.CreditNote;
import org.hgvc.webapp.ets.bo.Finance;
import org.hgvc.webapp.ets.bo.Invoice;
import org.hgvc.webapp.ets.bo.InvoiceDtl;
import org.hgvc.webapp.ets.bo.Payment;
import org.hgvc.webapp.ets.bo.PaymentDtl;
import org.hgvc.webapp.ets.bo.XSInvoiceType;
import org.hgvc.webapp.ets.constant.CommonConstant;
import org.hgvc.webapp.ets.spring.service.FinanceService;
import org.hgvc.webapp.ets.spring.service.MemberService;
import org.jocsb.base.AbstractBean;
import org.jocsb.base.comparator.GenericComparator;
import org.jocsb.base.exception.BaseException;
import org.jocsb.base.util.SpringUtils;



public class MemberInvListingBean extends AbstractBean {

	public static final String BEAN_NAME = "memberInvListingBean";

	// object
	private String memberSearch;
	private String agreementId;
	private List<MemberInvListingInfoBean> memberList;
	private List<MemberInvListingInfoBean> invList;
	private List<InvoiceDtl> invoiceDtlList;
	private List<XSInvoiceType> invoiceTypeList;
	private List<CreditNoteInfoBean> creditNoteList;
	private List<PaymentInfoBean> paymentList;
	private Invoice invoice;
	private Double advancePayment;
	private Finance finance;
	private Payment payment;
	private Double paymentAmt;
	private String actionNo;
	
	GenericComparator sorter = new GenericComparator(MemberInvListingInfoBean.class, "invNo");

	// service
	private FinanceService financeService;
	private MemberService memberService;

	
	//Action Outcome Variables
	private String memLstAcOutcome;
	private String invLstAcOutcome;
	private String newInvAcOutcome;
	private String newCnAcOutcome;
	private String newPayAcOutcome;
	
	// getters and setters
	public List<PaymentInfoBean> getPaymentList() {
		return paymentList;
	}
	public String getMemLstAcOutcome() {
		return memLstAcOutcome;
	}
	public void setMemLstAcOutcome(String memLstAcOutcome) {
		this.memLstAcOutcome = memLstAcOutcome;
	}
	public String getInvLstAcOutcome() {
		return invLstAcOutcome;
	}
	public void setInvLstAcOutcome(String invLstAcOutcome) {
		this.invLstAcOutcome = invLstAcOutcome;
	}
	public String getNewInvAcOutcome() {
		return newInvAcOutcome;
	}
	public void setNewInvAcOutcome(String newInvAcOutcome) {
		this.newInvAcOutcome = newInvAcOutcome;
	}
	public String getNewCnAcOutcome() {
		return newCnAcOutcome;
	}
	public void setNewCnAcOutcome(String newCnAcOutcome) {
		this.newCnAcOutcome = newCnAcOutcome;
	}
	public String getNewPayAcOutcome() {
		return newPayAcOutcome;
	}
	public void setNewPayAcOutcome(String newPayAcOutcome) {
		this.newPayAcOutcome = newPayAcOutcome;
	}
	
	public void setPaymentList(List<PaymentInfoBean> paymentList) {
		this.paymentList = paymentList;
	}

	public List<CreditNoteInfoBean> getCreditNoteList() {
		return creditNoteList;
	}

	public void setCreditNoteList(List<CreditNoteInfoBean> creditNoteList) {
		this.creditNoteList = creditNoteList;
	}

	public List<XSInvoiceType> getInvoiceTypeList() {
		return invoiceTypeList;
	}

	public void setInvoiceTypeList(List<XSInvoiceType> invoiceTypeList) {
		this.invoiceTypeList = invoiceTypeList;
	}

	public String getMemberSearch() {
		return memberSearch;
	}

	public void setMemberSearch(String memberSearch) {
		this.memberSearch = memberSearch;
	}

	public List<MemberInvListingInfoBean> getMemberList() {
		return memberList;
	}

	public void setMemberList(List<MemberInvListingInfoBean> memberList) {
		this.memberList = memberList;
	}

	public List<MemberInvListingInfoBean> getInvList() {
		if(invList!=null)
			Collections.sort(invList, sorter);
		return invList;
	}

	public void setInvList(List<MemberInvListingInfoBean> invList) {
		this.invList = invList;
	}

	public List<InvoiceDtl> getInvoiceDtlList() {
		return invoiceDtlList;
	}

	public void setInvoiceDtlList(List<InvoiceDtl> invoiceDtlList) {
		this.invoiceDtlList = invoiceDtlList;
	}

	public FinanceService getFinanceService() {
		return financeService;
	}

	public void setFinanceService(FinanceService financeService) {
		this.financeService = financeService;
	}

	public MemberService getMemberService() {
		return memberService;
	}

	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}

	public Double getPaymentAmt() {
		return paymentAmt;
	}

	public void setPaymentAmt(Double paymentAmt) {
		this.paymentAmt = paymentAmt;
	}

	// action
	public String initSalesAdminRole() {
		agreementId = null;
		memLstAcOutcome = "admRoleMemberListing";
		invLstAcOutcome = "admRoleInvListing";
		newInvAcOutcome = "admRoleNewInvoice";
		newPayAcOutcome = "admRoleNewPayment";
		newCnAcOutcome  = "admRoleNewCreditNote";
		return memLstAcOutcome;
	}
	public String initFinanceRole() {
		agreementId = null;
		memLstAcOutcome = "finRoleMemberListing";
		invLstAcOutcome = "finRoleInvListing";
		newInvAcOutcome = "finRoleNewInvoice";
		newPayAcOutcome = "finRoleNewPayment";
		newCnAcOutcome  = "finRoleNewCreditNote";
		return memLstAcOutcome;
	}

	public void searchMemberAction(ActionEvent event) {
		try {
			memberList = financeService.getMemberInvListingInfoBean(memberSearch);
		} catch (BaseException e) {
			initErrorBean(e);
			e.printStackTrace();
		}
	}
	
	public void listInvActionListener(ActionEvent event) {
		UIParameter param = (UIParameter) event.getComponent().findComponent("agreementId");
		agreementId = (String) param.getValue();
		try {
			HashMap hm = financeService.getFinListInvHm(agreementId);
			invList = (List<MemberInvListingInfoBean>) hm.get("invList");
			advancePayment = (Double) hm.get("advancePayment");
			finance = (Finance) hm.get("finance");
		} catch (BaseException e) {
			initErrorBean(e);
			e.printStackTrace();
		}
	}
	
	public void listInvActionListener(String agreementId){
		this.agreementId = agreementId;
		try {
			HashMap hm = financeService.getFinListInvHm(agreementId);
			invList = (List<MemberInvListingInfoBean>) hm.get("invList");
			advancePayment = (Double) hm.get("advancePayment");
			finance = (Finance) hm.get("finance");
		} catch (BaseException e) {
			initErrorBean(e);
			e.printStackTrace();
		}
	}
	
	public String newInvoiceAction() {
		return newInvoiceCommonAction(newInvAcOutcome);
	}
	
	private String newInvoiceCommonAction(String actionOutcome){
		try {
			invoice = newInvoice();
			invoice.setRefId(agreementId);
			invoiceTypeList = financeService.getInvoiceTypeList();
			invoiceDtlList = new ArrayList<InvoiceDtl>();
			invoiceDtlList.add(newInvoiceDtl());
		} catch (BaseException e) {
			initErrorBean(e);
			e.printStackTrace();
		}
		return actionOutcome;
	}
	
	public String newPaymentAction() {
		return newPaymentCommonAction(newPayAcOutcome);
	}
	public String newPaymentCommonAction(String actionOutcome) {
		paymentAmt = null;
		payment = new Payment();
		payment.setRefId(agreementId);
		payment.setFinance(finance);
		paymentList = new ArrayList<PaymentInfoBean>();
		for (MemberInvListingInfoBean infoBean : invList) {
			
			if(infoBean.getInvoiceDtl().getItemAmount()>infoBean.getInvoiceDtl().getPaidAmount()){
				PaymentInfoBean paymentInfoBean = new PaymentInfoBean();
				paymentInfoBean.setInvAmt(infoBean.getInvAmt());
				paymentInfoBean.setCurrentPaidAmt(infoBean.getInvoiceDtl().getPaidAmount());
				paymentInfoBean.setInvoiceNo(infoBean.getInvNo());
				paymentInfoBean.setInvoiceDtl(infoBean.getInvoiceDtl());
				paymentInfoBean.setPaymentDtl(newPaymentDtl(infoBean.getInvoiceDtl()));
				paymentList.add(paymentInfoBean);
			}
		}
		return actionOutcome;
	}

	public String newCreditNoteAction() {
		return newCreditNoteCommonAction(newCnAcOutcome);
	}
	public String newCreditNoteCommonAction(String actionOutcome) {
		creditNoteList = new ArrayList<CreditNoteInfoBean>();
		for (MemberInvListingInfoBean infoBean : invList) {
			CreditNoteInfoBean creditNote = new CreditNoteInfoBean();
			creditNote.setCreditNote(newCreditNote(infoBean.getInvoiceDtl()));
			creditNoteList.add(creditNote);
		}
		return actionOutcome;
	}
	
	public void addInvDtlAction(ActionEvent event) {
		invoiceDtlList.add(newInvoiceDtl());
	}

	public void removeInvDtlAction(ActionEvent event) {
		UIParameter param = (UIParameter) event.getComponent().findComponent("index");
		int index = Integer.parseInt(param.getValue().toString());
		invoiceDtlList.remove(index);
	}

	public String createInvoiceAction() {
		String outcome = invLstAcOutcome;
		return createInvoiceCommonAction(outcome);
	}
	public String createInvoiceCommonAction(String actionOutcome) {
		String outcome = actionOutcome;
		try {
			invoice.setInvoiceAmount(getCalculateTotalInvAmt());
			financeService.saveInvoice(invoice, invoiceDtlList);
			invList = financeService.getInvListByAgreementId(agreementId);
		} catch (BaseException e) {
			outcome = null;
			initErrorBean(e);
			e.printStackTrace();
		}
		return outcome;
	}
	
	public String cancelFromCreateInv() {
		return invLstAcOutcome;
	}

	public String createCreditNoteAction() {
		String outcome = invLstAcOutcome;
		return createCreditNoteCommonAction(outcome);
	}
	public String createCreditNoteCommonAction(String actionOutcome) {
		String outcome = actionOutcome;
		try {
			financeService.saveCreditNote(getSelectedCreditNote(), getThisUser());
			invList = financeService.getInvListByAgreementId(agreementId);
			
			listInvActionListener(agreementId);
			
		} catch (BaseException e) {
			outcome = null;
			initErrorBean(e);
			e.printStackTrace();
		}
		return outcome;
	}

	public String cancelFromCreditNote() {
		return invLstAcOutcome;
	}

	public String createPaymentAction() {
		String outcome = invLstAcOutcome;
		return createPaymentCommonAction(outcome);
	}
	public String createPaymentCommonAction(String actionOutcome) {
		String outcome = actionOutcome;
		try {
			validatePaymentAmtRequired();
			List<PaymentInfoBean> paymentList = getSelectedPayment();
			if(paymentList.size()>0){
				financeService.savePayment(payment, getSelectedPayment(), paymentAmt, getThisUser(),actionNo);
				listInvActionListener(agreementId);
				
			}
		} catch (BaseException e) {
			outcome = null;
			initErrorBean(e);
			e.printStackTrace();
		}
		return outcome;
	}

	public String createAdvancePaymentAction() {
		String outcome = invLstAcOutcome;
		return createAdvancePaymentCommonAction(outcome);
	}
	private String createAdvancePaymentCommonAction(String actionOutcome) {
		String outcome = actionOutcome;
		try {
			List<PaymentInfoBean> paymentList = getSelectedPayment();
			if(paymentList.size()>0){
				financeService.saveAdvancePayment(payment, getSelectedPayment(), getThisUser());
				listInvActionListener(agreementId);
			}
		} catch (BaseException e) {
			outcome = null;
			initErrorBean(e);
			e.printStackTrace();
		}
		return outcome;
	}
	
	public String cancelFromcreatePayment() {
		return invLstAcOutcome;
	}

	// method
	public Double getTotalInvAmt() {
		Double totalInvAmt = 0.0;
		for (MemberInvListingInfoBean temp : invList) {
			totalInvAmt = totalInvAmt + temp.getInvAmt();
		}
		return totalInvAmt;
	}

	public Double getTotalPaidAmt() {
		Double totalPaidAmt = 0.0;
		for (MemberInvListingInfoBean temp : invList) {
			
			Double amountPaid = temp.getAmtPaid();
			if (amountPaid==null) amountPaid=0.0;
			totalPaidAmt = totalPaidAmt + amountPaid;
		}
		return totalPaidAmt;
	}

	public Double getCalculateTotalInvAmt() {
		Double totalInvAmt = 0.0;
		for (InvoiceDtl temp : invoiceDtlList) {
			totalInvAmt = totalInvAmt + temp.getItemAmount();
		}
		return totalInvAmt;
	}

	public Double getAdvancePayment() {
		return advancePayment;
	}

	public void setAdvancePayment(Double advancePayment) {
		this.advancePayment = advancePayment;
	}

	public Integer getInvDtlListSize() {
		if (invoiceDtlList != null)
			return invoiceDtlList.size();
		else
			return 0;
	}

	public List<SelectItem> getSelectInvTypeList() {
		List<SelectItem> selectList = new ArrayList<SelectItem>();
		for (XSInvoiceType type : invoiceTypeList) {
			selectList.add(new SelectItem(type.getCode(), type.getDescription()));
		}
		return selectList;
	}

	public MemberInvListingInfoBean getSelectedMember() {
		MemberInvListingInfoBean member = new MemberInvListingInfoBean();
		for (MemberInvListingInfoBean temp : memberList) {
			if (temp.getAgreementId().equalsIgnoreCase(agreementId)) {
				member = temp;
				break;
			}
		}
		return member;
	}

	public List<CreditNoteInfoBean> getSelectedCreditNote() {
		List<CreditNoteInfoBean> selectedCreditNoteList = new ArrayList<CreditNoteInfoBean>();
		for (CreditNoteInfoBean temp : creditNoteList) {
			if (temp.isSelected()) {
				selectedCreditNoteList.add(temp);
			}
		}
		return selectedCreditNoteList;
	}
	
	public List<PaymentInfoBean> getSelectedPayment() {
		List<PaymentInfoBean> selectedPaymentList = new ArrayList<PaymentInfoBean>();
		for (PaymentInfoBean temp : paymentList) {
			if (temp.isSelected()) {
				selectedPaymentList.add(temp);
			}
		}
		return selectedPaymentList;
	}

	public Invoice newInvoice() {
		Invoice invoice = new Invoice();
		invoice.setIsDeleted(CommonConstant.NOT_DELETED);
		invoice.setCreatedBy(getThisUser());
		invoice.setCreatedDate(new Date());
		invoice.setFinance(finance);
		return invoice;
	}

	public InvoiceDtl newInvoiceDtl() {
		InvoiceDtl invoiceDtl = new InvoiceDtl();
		invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		invoiceDtl.setCreatedBy(getThisUser());
		invoiceDtl.setCreatedDate(new Date());
		invoiceDtl.setItemAmount(0.0);
		invoiceDtl.setPaidAmount(0.0);
		invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
		invoiceDtl.setInvoice(invoice);
		return invoiceDtl;
	}

	public CreditNote newCreditNote(InvoiceDtl invoiceDtl) {
		CreditNote creditNote = new CreditNote();
		creditNote.setCreatedBy(getThisUser());
		creditNote.setCreatedDate(new Date());
		creditNote.setCreditAmount(0.0);
		creditNote.setIsDeleted(CommonConstant.NOT_DELETED);
		creditNote.setInvoiceDtl(invoiceDtl);
		creditNote.setDescn(invoiceDtl.getItemDesc());
		return creditNote;
	}

	public PaymentDtl newPaymentDtl(InvoiceDtl invoiceDtl) {
		PaymentDtl paymentDtl = new PaymentDtl();
		paymentDtl.setPayment(payment);
		paymentDtl.setRefId(invoiceDtl.getInvoiceDtlId());
		paymentDtl.setDesc(invoiceDtl.getItemDesc());
		paymentDtl.setCreatedBy(getThisUser());
		paymentDtl.setCreatedDate(new Date());
		paymentDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		paymentDtl.setAmount(0.0);
		return paymentDtl;
	}

	// validation
	public void validatePaymentAmtRequired() throws BaseException {
		if(paymentAmt==null)
			throw new BaseException(SpringUtils.getMessage("error.is.required", new Object[]{"Amount"}));
	}
	
	public void setActionNo(String actionNo) {
		this.actionNo = actionNo;
	}
	public String getActionNo() {
		return actionNo;
	}
}
